﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CommonLib;

namespace MLO
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private bool loaded = false;

        private void load_but_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Xml File|*.xml";
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                loaded = true;
                GenSource.all_data = new DataSet();
                DataSet all_data = GenSource.all_data;
                DataSet loaded_ds = new DataSet();
                loaded_ds.ReadXml(ofd.FileName);

                //загрузка доменов
                all_data.Tables.Add(loaded_ds.Tables["domens"].Copy());
                all_data.Tables.Add(loaded_ds.Tables["domens_params"].Copy());

                //загрузка фреймов
                GenSource.all_frames.Clear();
                GenSource.exemplars.Clear();
                GenSource.prototypes.Clear();
                GenSource.situations.Clear();
                DataTable table = loaded_ds.Tables["Frames"];
                if (table != null)
                {
                    foreach (DataRow dr in loaded_ds.Tables["Frames"].Rows)
                    {
                        Frame frm = null;
                        switch (dr["type"].ToString())
                        {
                            case "Prototype":
                                GenSource.prototypes.Add(frm = new Frame(dr["name"].ToString(), CommonLib.FrameType.Prototype));
                                break;
                            case "Exemplar":
                                GenSource.exemplars.Add(frm = new Frame(dr["name"].ToString(), CommonLib.FrameType.Exemplar));
                                break;
                            case "Situation":
                                GenSource.situations.Add(frm = new Frame(dr["name"].ToString(), CommonLib.FrameType.Situation));
                                break;
                        }
                        if (frm != null)
                            GenSource.all_frames.Add(frm);
                    }
                }
                //загрузка слотов
                table = loaded_ds.Tables["Slots"];
                if (table != null)
                {
                    foreach (DataRow dr in table.Rows)
                    {
                        Frame f = GenSource.all_frames.Find(o => o.Name == dr["id_frame"].ToString());
                        if (f != null)
                        {
                            Slot s = new Slot(dr["name"].ToString());
                            switch (dr["type"].ToString())
                            {
                                case "Regular":
                                    s.Type = SlotType.Regular;
                                    s.DomainID = dr["id_domain"].ToString();
                                    s.Default = dr["default"].ToString();
                                    switch (dr["inherit"].ToString())
                                    {
                                        case "Range":
                                            s.Inherit = TypeInherit.Range;
                                            break;
                                        case "Overwrite":
                                            s.Inherit = TypeInherit.Overwrite;
                                            break;
                                        case "Same":
                                            s.Inherit = TypeInherit.Same;
                                            break;
                                    }
                                    break;
                                case "SubFrame":
                                    s.Type = SlotType.SubFrame;
                                    s.Subframe = GenSource.all_frames.Find(o => o.Name == dr["subframe"].ToString());
                                    break;
                                case "AKO":
                                    s.Type = SlotType.AKO;
                                    s.Subframe = GenSource.all_frames.Find(o => o.Name == dr["subframe"].ToString());
                                    break;
                                case "Error":
                                    s.Type = SlotType.Error;
                                    s.Subframe = GenSource.all_frames.Find(o => o.Name == dr["subframe"].ToString());
                                    break;
                                case "Next":
                                    s.Type = SlotType.Next;
                                    s.Subframe = GenSource.all_frames.Find(o => o.Name == dr["subframe"].ToString());
                                    break;
                                case "Production":
                                    s.Type = SlotType.Production;
                                    DataRow[] productions = loaded_ds.Tables["Productions"].Select("owner_frame = '" + f.Name + "'");
                                    DataRow product = null;
                                    foreach (DataRow row in productions)
                                        if (row["owner_slot"].ToString() == s.Name)
                                        {
                                            product = row;
                                            break;
                                        }
                                    Production p = new Production(s);
                                    Frame var_frame = GenSource.all_frames.Find(o => o.Name == product["frame"].ToString());
                                    Slot var_slot = (Slot)var_frame.SearchSlot(product["slot"].ToString());
                                    if (var_frame == f)
                                        p.Item = new Item(var_slot, var_slot.FullName);
                                    else
                                        p.Item = new Item(var_slot, s.FullName + "." + var_slot.Name);
                                    p.Operation = product["operation"].ToString();
                                    switch (product["type"].ToString())
                                    {
                                        case "Enum":
                                            p.Type = CommonLib.ValueType.Enum;
                                            p.Value = new Item(null, product["value"].ToString());
                                            break;
                                        case "Frame":
                                            p.Type = CommonLib.ValueType.Frame;
                                            String value = product["value"].ToString();
                                            if (value.Split('.').Count() == 2)
                                            {
                                                Slot value_slot = (Slot)GenSource.all_frames.Find(o => o.Name == value.Split('.')[0]).SearchSlot(value.Split('.')[1]);
                                                p.Value = new Item(value_slot, value);
                                            }
                                            else
                                            {
                                                Slot value_slot = (Slot)((GenSource.all_frames.Find(o => o.Name == value.Split('.')[0]).SearchSlot(value.Split('.')[1]) as Slot).Subframe.SearchSlot(value.Split('.')[2]));
                                                p.Value = new Item(value_slot, value);
                                            }
                                            break;
                                        case "Int":
                                            p.Type = CommonLib.ValueType.Int;
                                            p.Value = new Item(null, product["value"].ToString());
                                            break;
                                        case "IntVar":
                                            p.Type = CommonLib.ValueType.IntVar;
                                            p.Type = CommonLib.ValueType.Frame;
                                            value = product["value"].ToString();
                                            if (value.Split('.').Count() == 2)
                                            {
                                                Slot value_slot = (Slot)GenSource.all_frames.Find(o => o.Name == value.Split('.')[0]).SearchSlot(value.Split('.')[1]);
                                                p.Value = new Item(value_slot, value);
                                            }
                                            else
                                            {
                                                Slot value_slot = (Slot)(GenSource.all_frames.Find(o => o.Name == value.Split('.')[0]).SearchSlot(value.Split('.')[1]) as Slot).Subframe.SearchSlot(value.Split('.')[2]);
                                                p.Value = new Item(value_slot, value);
                                            }
                                            break;
                                    }
                                    s.Production = p;
                                    break;
                            }
                            f.AddSlot(s);
                        }
                    }
                }

                //добавление родительских слотов
                foreach (Frame frm in GenSource.all_frames)
                {
                    if (frm.GetSlots(SlotType.AKO).Count > 0)
                    {
                        foreach (Slot slt in GenSource.GetHeritSlots(((Slot)frm.GetSlots(SlotType.AKO)[0]).Subframe.Name))
                        {
                            if (frm.SearchSlot(slt.Name) == null)
                                frm.AddSlot(slt);
                        }
                    }
                }
            }
        }

        class FrameSlot
        {
            public FrameSlot(Frame Frame, Slot Slot)
            {
                frame = Frame;
                slot = Slot;
            }
            public Frame frame;
            public Slot slot;
        }

        private List<List<FrameSlot>> getFS(Slot slt, int depth, List<ISlot> slots)
        {
            List<List<FrameSlot>> result = new List<List<FrameSlot>>();
            if (depth < slots.Count - 1)
            {
                List<List<FrameSlot>> query = getFS(slots[depth + 1] as Slot, depth + 1, slots);
                foreach (Frame fslt in GenSource.BindSubFrames(slt.Subframe.Name))
                {
                    foreach (List<FrameSlot> lfs in query)
                    {
                        List<FrameSlot> added = new List<FrameSlot>();
                        foreach (FrameSlot fs in lfs)
                            added.Add(fs);
                        added.Add(new FrameSlot(fslt, slt));
                        result.Add(added);
                    }
                }
            }
            else
            {
                foreach (Frame fslt in GenSource.BindSubFrames(slt.Subframe.Name))
                {
                    List<FrameSlot> added = new List<FrameSlot>();
                    added.Add(new FrameSlot(fslt, slt));
                    result.Add(added);
                }
            }
            return result;
        }

        private void start_but_Click(object sender, EventArgs e)
        {
            if (loaded)
            {
                //выделяем ситуации нижнего уровня
                List<Frame> active_stns = new List<Frame>();
                List<Frame> temp = new List<Frame>();
                foreach (Frame frm in GenSource.situations)
                {
                    if (frm.GetSlots(SlotType.AKO).Count > 0)
                        temp.Add(GenSource.situations.Find(o => o.Name == ((Slot)frm.GetSlots(SlotType.AKO)[0]).Subframe.Name));
                }
                foreach (Frame frm in GenSource.situations)
                {
                    if (!temp.Contains(frm))
                        active_stns.Add(frm);
                }
                richTextBox1.Text = "";
                //обходим все ситуации нижнего уровня
                foreach (Frame frm in active_stns)
                {
                    //привязываем всевозможные комбинации субфреймов
                    List<ISlot> sfr_slts = frm.GetSlots(SlotType.SubFrame);
                    List<List<FrameSlot>> sub_sets = new List<List<FrameSlot>>();
                    sub_sets = getFS(sfr_slts[0] as Slot, 0, sfr_slts);
                    for (int i = sub_sets.Count - 1; i >= 0; i--)
                    {
                        //bool boo = true;
                        Frame fr = sub_sets[i][0].frame;
                        /*foreach (FrameSlot fs in sub_sets[i])
                            boo = boo && fr == fs.frame;
                        if (boo)
                            sub_sets.RemoveAt(i);*/
                    }
                    List<ISlot> qstn_slts = frm.GetSlots(SlotType.Question);
                    List<ISlot> actn_slts = frm.GetSlots(SlotType.Result);
                    int changed = 0;
                    richTextBox1.Text += "Ситуация " + frm.Name + ":\n";
                    /*for (int i = sub_sets.Count - 1; i >= 0; i--)
                    {
                        List<FrameSlot> lst = sub_sets[i];
                        bool still_binded = true;
                        foreach (FrameSlot fs in lst)
                            ;// still_binded = still_binded && BindSubFrames(all_frames.Find(o => o.Name == fs.slot.Value.ToString()).Name).Contains(fs.frame);

                        if (still_binded)
                        {
                            if (CheckQuestions(frm, lst, qstn_slts))
                            {
                                int ij = 0;
                                foreach (Slot slt in frm.GetSlots(SlotType.SubFrame))
                                {
                                    richTextBox1.Text += slt.Name + " = " + lst[ij].frame.Name + ", ";
                                    ij++;
                                }
                                richTextBox1.Text += "\n";
                                DoActions(frm, lst, actn_slts);
                                sub_sets.RemoveAt(i);
                                changed++;
                            }
                        }
                        else
                            sub_sets.RemoveAt(i);
                    }*/
                    if (changed == 0)
                    {
                        if (sub_sets.Count != 0)
                        {
                            ////MoveError OR Parent
                        }
                    }
                    else
                    {
                        //MoveNext 
                        if (sub_sets.Count != 0)
                        {
                            //Parent
                        }
                    }
                }
            }
            else
                MessageBox.Show("Загрузите Базу фреймов!");
        }
    }
}
